
/* 
 * Lunula Javascript VM
 * 
 * Author: Anthony Fairchild
 * 
 */

function Cons(car, cdr)
{
    this.Car = car;
    this.Cdr = cdr;
}

Cons.ReverseConsFromArray = function(array)
{
    var c = null;
    for(var item in array)
    {
        c = new Cons(array[item]);
    }
    return c;
};

Cons.ConsFromArray = function(array)
{
    return Cons.Reverse(ReverseConsFromArray(cons));
};

Cons.prototype.Reverse = function(cons)
{
    
};

function Instruction(code)
{
    this.OpCodes = {        
        SaveContinuation  : 0,
        FetchLiteral      : 1,
        Push              : 2 ,
        Apply             : 3,
        Bind              : 4,
        MakeClosure       : 5,
        ToplevelGet       : 6,
        ToplevelSet       : 7,
        LocalGet          : 8,
        LocalSet          : 9,
        Return            : 10,
        End               : 11,
        Jump              : 12,
        JumpIfFalse       : 13,
        BindVarArgs       : 14
    };
    this.OpCode = code & 0x3f;
    this.A = (code >> 6) & 0x1FFF;
    this.B = code >> 19;
    this.AX = code >> 6;
}

function Continuation(cont, envt, evalStack, template, pc)
{
    this.CONT = cont;
    this.ENVT = envt;
    this.EVAL_STACK = evalStack;
    this.TEMPLATE = template;
    this.PC = pc;
}

function Template(name, literals, code)
{
    this.Name = name;    
    this.Literals = literals;
    this.Code = code;
}

function Environment(parent, bindings)
{
    this.Parent = parent; 
    this.Bindings = bindings; // an array of values
}

function Closure(template, envt)
{
    this.Template = template;
    this.Envt = envt;    
}

function LunulaVM()
{
    // Toplevel Environment
    this.ToplevelEnv = [];

    // REGISTERS
    this.PC = 0;
    this.CONT = null;
    this.TEMPLATE = null;
    this.EVAL_STACK = null;
    this.ENVT = null;
    this.VALUE = null;
}

LunulaVM.prototype.RunClosure = function(closure, params)
{
    var PREV_CONT = CONT;
    var PREV_ENVT = ENVT;
    var PREV_EVAL_STACK = EVAL_STACK;
    var PREV_TEMPLATE = TEMPLATE;
    var PREV_PC = PC;
    

    CONT = null;
    ENVT = closure.Envt;
    EVAL_STACK = 
};

function ByteStream(str)
{
    this.str = str;
    this.ptr = 0;    
}

ByteStream.prototype.ReadByte = function()
{
    var b = this.str.charCodeAt(this.ptr) & 0xFF;
    this.ptr++;
    return b;
};

ByteStream.prototype.ReadWord = function()
{
    var word = this.ReadByte();
    word = word | (this.ReadByte() << 8); 
    return word;
};

ByteStream.prototype.ReadChar = function()
{
   return String.fromCharCode(this.ReadWord());    
};

ByteStream.prototype.ReadDWord = function()
{
    var dword = this.ReadWord();
    dword = dword | (this.ReadWord() << 16); 
    return dword;
};

function loadLunulaFile(fileName)
{
    var s = readFile(fileName);
    var bs = new ByteStream(s);
};

